package com.jiangyg.mall.authz.support;

import com.jiangyg.mall.core.utils.bean.BeanUtils;
import com.jiangyg.mall.core.utils.time.DateUtils;
import io.jsonwebtoken.*;
import org.apache.commons.collections.MapUtils;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.Map;

/**
 * 类描述：token管理工具
 *
 * @author jiangyg
 * @version 2.0
 * @date 2019-10-30
 */
public class TokenUtils {

    /**
     * 功能描述：生成token
     *
     * @param claims         认证信息
     * @param base64Security base64位加密串
     * @param timeout        失效时间，单位秒
     * @return token
     */
    public static String build(Map<String, Object> claims, String base64Security, int timeout) {
        // 时间
        Date now = new Date();
        Date expiredDate = DateUtils.addSeconds(now, timeout);
        // token构建
        JwtBuilder builder = Jwts.builder();
        builder.addClaims(claims);
        // 生成签名
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS384;
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
        builder.signWith(signatureAlgorithm, signingKey);
        // 设置签发时间
        builder.setIssuedAt(now);
        // 设置token过期时间
        builder.setExpiration(expiredDate)/*.setNotBefore(now)*/;
        // 压缩
        builder.compressWith(CompressionCodecs.GZIP);
        return builder.compact();
    }

    /**
     * 功能描述：解析token
     *
     * @param token          token字符串
     * @param base64Security base64位加密串
     * @param clazz          转换类型
     * @return bean
     */
    public static <T> T parse(String token, String base64Security, Class<T> clazz) throws Exception {
        Claims claims = parse(token, base64Security);
        return BeanUtils.mapToBean(claims, clazz);
    }

    /**
     * 功能描述：解析token
     *
     * @param token          token字符串
     * @param base64Security base64位加密串
     * @return Claims
     */
    public static Claims parse(String token, String base64Security) {
        JwtParser parse = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(base64Security));
        return parse.parseClaimsJws(token).getBody();
    }

    /**
     * 功能描述：获得token中的签发时间
     *
     * @param token          token字符串
     * @param base64Security base64位加密串
     * @return 签发时间
     */
    public static Date issuedAt(String token, String base64Security) {
        Claims claims = parse(token, base64Security);
        return issuedAt(claims);
    }

    /**
     * 功能描述：获得token中的签发时间
     *
     * @param claims 签发信息
     * @return 签发时间
     */
    public static Date issuedAt(Claims claims) {
        return new Date(MapUtils.getLong(claims, "iat") * 1000);
    }

    /**
     * 功能描述：获得token中的过期时间
     *
     * @param claims 签发信息
     * @return 过期时间
     */
    public static Date exp(Claims claims) {
        return new Date(MapUtils.getLong(claims, "exp") * 1000);
    }

    /**
     * 功能描述：token是否过期
     *
     * @param token          token字符串
     * @param base64Security base64位加密串
     * @return 是否过期
     */
    public static boolean isExpired(String token, String base64Security) {
        Claims claims = parse(token, base64Security);
        return isExpired(claims);
    }

    /**
     * 功能描述：token是否过期
     *
     * @param claims 签发信息
     * @return 是否过期
     */
    public static boolean isExpired(Claims claims) {
        Date exp = new Date(MapUtils.getLong(claims, "exp") * 1000);
        return exp.before(new Date());
    }

}
